﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ManagedVC1;

namespace EncoderTester
{
    public static class EncoderManager
    {
        public static VC1Encoder CreateEncoder(EncoderConfiguration config)
        {
            VC1Encoder encoder = new VC1Encoder();

            encoder.Config.BitRate = config.Video.BitRate;
            encoder.Config.ComplexityLevel = config.Video.ComplexityLevel;
            encoder.Config.FrameRate = FrameRates.All.FirstOrDefault(fr => fr.Rate == config.Video.FrameRate);
            encoder.Config.InterlacedSource = config.Video.InterlacedSource;
            encoder.Config.MaxHeight = config.Video.MaximumHeight;
            encoder.Config.MaxKeyFrameDistance = config.Video.MaxKeyFrameDistance;
            encoder.Config.MaxWidth = config.Video.MaximumWidth;
            encoder.Config.NumOfBFrames = config.Video.NumBFrames;
            encoder.Config.PeakBitRate = config.Video.PeakBitRate;
            encoder.Config.Profile = config.Basic.Profile;
            encoder.Config.QP = config.Video.QP;
            encoder.Config.RateControlMode = config.Basic.RateControlMode;
            encoder.Config.VBVBufferInBytes = 8 * config.Video.BitRate;

            encoder.Filter.UseDenoise = config.Filters.UseDenoise;
            encoder.Filter.UseInLoop = config.Filters.UseInLoop;
            encoder.Filter.UseMedian = config.Filters.UseMedian;
            encoder.Filter.UseNoiseEdgeRemoval = config.Filters.UseNoiseEdgeRemoval;
            encoder.Filter.UseOverlapSmoothing = config.Filters.UseOverlapSmoothing;

            encoder.MotionEstimation.DeltaMVRangeIndex = config.MotionEstimation.DeltaMVRangeIndex;
            encoder.MotionEstimation.MBModeCost = config.MotionEstimation.MacroblockModeCost;
            encoder.MotionEstimation.MotionSearchLevel = config.MotionEstimation.MotionSearchLevel;
            encoder.MotionEstimation.MotionSearchMethod = config.MotionEstimation.MotionSearchMethod;
            encoder.MotionEstimation.MVCost = config.MotionEstimation.MotionVectorCost;
            encoder.MotionEstimation.MVRange = config.MotionEstimation.MotionVectorRange;

            encoder.Quantization.AdaptiveQuantization = config.Quantization.AdaptiveQuantization;
            encoder.Quantization.DQuantBStrength = config.Quantization.BFrameStrength;
            encoder.Quantization.DQuantOption = config.Quantization.DifferentialQuantization;
            encoder.Quantization.DQuantPStrength = config.Quantization.PFrameStrength;

            return encoder;
        }

        public static void SetAdvancedSettings(VC1Encoder encoder, EncoderConfiguration config)
        {
            uint affinityMask = 0;
            for (int i = 0; i < config.Advanced.NumThreads; i++) affinityMask |= (uint)(1 << i);

            encoder.AdaptiveGOP = config.Advanced.AdaptiveGOP;
            encoder.BFrameDeltaQP = config.Advanced.BFrameDeltaQP;
            encoder.ClosedEntryPoint = config.Advanced.ClosedEntryPoint;
            encoder.KeyPopReduction = config.Advanced.KeyPopReduction;
            encoder.LetterBoxPresent = config.Advanced.LetterBoxPresent;
            encoder.LookAhead = config.Advanced.LookAhead;
            encoder.OutputMode = (OutputModeType)config.Advanced.OutputMode;
            encoder.VideoType = config.Advanced.VideoType;
            encoder.NumThreads = new ThreadRunInfo(config.Advanced.NumThreads, affinityMask);
        }
    }
}
